#include "ObjectManager.h"

ObjectManager::ObjectManager()
{
	useLight = false;
	skyBox = 0;
	shadowBuffer.depthAsTexture = true;
	shadowBuffer.colorAsTexture = true;
	useLight = false;
	GraphicsManager::GetGraphicsManager()->GenFrameBuffer(shadowBuffer, 1024, 1024);
};

ObjectManager::~ObjectManager()
{
	for (ObjectIterator iterator = objects.begin(); iterator != objects.end(); iterator++)
	{
		Object3D *object3D = *iterator;
		SAFE_DEL(object3D);
	}
	objects.clear();
};

void ObjectManager::AddObject(Object3D *object)
{
	objects.push_back(object);
};

void ObjectManager::Render()
{
	static Cube3D renderCube;
	GraphicsManager *graphics = GraphicsManager::GetGraphicsManager();
	// graphics->UseEffect(effect_id::SHADOW);


	//glCullFace(GL_FRONT);
	// Create the shadow map
	Matrix lightVP;
	lightVP.LoadPerperstive(90, 1.0f, 0.1f, 15.0f);    
	lightVP.Translate(-lightSource.position.x, -lightSource.position.y, -lightSource.position.z);
	lightVP.RotateX(90); 


	graphics->UseFrameBuffer(&shadowBuffer);


	//glCullFace(GL_BACK);
	graphics->UseFrameBuffer();
	Matrix viewProjection;
	// ProjectionMatrix goes here.
	viewProjection.LoadPerperstive(45, SCREEN_W / (float) SCREEN_H, 0.1f, 1000.0f);

	// Mutiply with View Matrix  (Camera Matrix)
	viewProjection*= *camera.GetTransform();

	//viewProjection.LoadPerperstive(90, 1.0f, 0.1f, 20.0f);
	//viewProjection.RotateX(90);
	for (ObjectIterator iterator = objects.begin(); iterator != objects.end(); iterator++)
	{
		Object3D *object3D = *iterator;
		//Matrix wvpMatrix = viewProjection;
		//Matrix lightWVP = lightVP;
		// Multiply with World Matrix
		//Matrix *transform = object3D->GetTransform();
		//wvpMatrix*= *transform;
		//lightWVP*= *transform;

		graphics->UseEffect(object3D->effectId);
		//graphics->SetInt(shader3d::UN_USELIGHTING, useLight);
		//graphics->SetMatrix(shader3d::UN_WVPMATRIX, wvpMatrix);
		//graphics->SetMatrix(shader3d::UN_LIGHTWVP, lightWVP);
		graphics->SetTexture(shader3d::UN_SHADOWMAP, shadowBuffer.depthBuffer);
		//object3D->ApplyEffect(this, graphics);
		// Render the Object

		object3D->Render(this, graphics, &viewProjection, &lightVP);
	}

	renderCube.position = lightSource.position;
	renderCube.scale = Vector3(0.3f, 0.3f, 0.3f);
	renderCube.material.diffuse = lightSource.diffuse;

	Matrix wvpMatrix = viewProjection;
	// Multiply with World Matrix
	char tmpOption[3]={0,1,2};
	wvpMatrix*= *renderCube.GetTransform(tmpOption);
	graphics->SetMatrix(shader3d::UN_WVPMATRIX, wvpMatrix);
	graphics->SetInt(shader3d::UN_USELIGHTING, 0);


	renderCube.ApplyEffect(this, graphics);   

	if (skyBox)
	{

		glDisable(GL_CULL_FACE);
		wvpMatrix = viewProjection;
		// render the sky box
		graphics->UseEffect(effect_id::SKYBOX);

		graphics->SetTexture(skybox::UN_SKYBOX, skyBox, 0, GL_TEXTURE_CUBE_MAP);
		renderCube.rotation = Vector3();
		renderCube.position = camera.position;
		renderCube.scale = Vector3(5.0f, 5.0f, 5.0f);
		char tmpOption[3]={0, 1, 2};
		wvpMatrix*= *renderCube.GetTransform(tmpOption);
		graphics->SetMatrix(skybox::UN_WVPMATRIX, wvpMatrix);
		renderCube.Render(this, graphics, &viewProjection, &lightVP);

		glEnable(GL_CULL_FACE);
	}

};
